#include "udpServer.hpp"
#include <iostream>
#include <fstream>
#include <unordered_map>
#include <memory>
using namespace std;
using namespace Server;

const string dictTxt = "./dict.txt";

static void Usage(string proc)
{
    cout << "\nUsage:\n\t" << proc << " lock_port\n\n";
}

static bool cutString(const string &line, string &key, string &value, const string &sep)
{
    // printf:打印
    size_t pos = line.find(sep);
    if (pos == string::npos)
        return false;
    key = line.substr(0, pos);
    value = line.substr(pos + sep.size());
    return true;
}

unordered_map<string, string> dict;
static void initDict()
{
    ifstream in(dictTxt, ios::binary);
    if (!in.is_open())
    {
        cerr << "open file error: " << errno << " : " << strerror(errno) << endl;
        exit(OPENDICT_ERR);
    }
    string line;
    std::string key, value; // 用于保存line中的key和value
    while (getline(in, line))
    {
        // 截取数据
        if (cutString(line, key, value, ":"))
        {
            // 保存数据到哈希表中
            dict.insert(make_pair(key, value));
        }
        else
            cout << "配置文件错误" << line;
    }

    in.close();

    cout << "服务器加载字典成功" << endl;
}

void reload(int signo)
{
    (void)signo;
    initDict();
}

static void debugPrint()
{
    for (const auto &dt : dict)
    {
        cout << dt.first << ":" << dt.second << endl;
    }
}

// 对收到的信息进行翻译，并且将信息发回去
void handlerMessage(const int &sockfd, const string &clientip, const uint16_t &clientport, const string &message)
{
    // 就可以对message进行处理，而不去关心message是怎么来的
    // 从而实现了通信和处理信息的解耦

    // 1.简单的业务逻辑
    string response_message;
    auto iter = dict.find(message);
    if (iter == dict.end())
        response_message = "unknown";
    else
        response_message = dict[message];

    // 2.将信息转发回客户端
    struct sockaddr_in client;
    bzero(&client, sizeof(client));

    client.sin_family = AF_INET;
    client.sin_port = htons(clientport);
    client.sin_addr.s_addr = inet_addr(clientip.c_str());
    sendto(sockfd, response_message.c_str(), sizeof(response_message), 0, (struct sockaddr *)&client, sizeof(client));
}

// ./UdpServer ip prot
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);

    // 使用信号支持简单的热加载
    signal(2, reload);

    initDict(); // 服务器先加载字典
    // debugPrint(); // 测试加载

    std::unique_ptr<udpserver> usvr(new udpserver(handlerMessage, port));
    usvr->initServer();
    usvr->start();
    return 0;
}